<script setup lang="ts" generic="T">
import { Download, Filter } from '@element-plus/icons-vue'
import { useSimpleExportLists } from './useSimpleExportLists'
import type { TableColumn, TableScopedColumn } from '@/types'

defineOptions({
  inheritAttrs: false,
})
const props = withDefaults(
  defineProps<{
    loading: boolean
    lists: T[]
    columns: TableColumn<T>[]
    height?: string | number
    operateWidth?: string | number
    showToolbox?: boolean
    popoverWidth?: string | number
    operateAlign?: string
    noBorderBottom?: boolean
    customDownload?: boolean
    hideDownload?: boolean
  }>(),
  {
    loading: true,
    operateWidth: '100px',
    height: '100%',
    popoverWidth: 'auto',
    operateAlign: 'center',
  },
)
const emits = defineEmits<{
  (e: 'download', v: any[]): void
}>()
// 显示声明插槽类型
defineSlots<{
  operate: (props: {
    row: T
    column: TableScopedColumn
    index: number
  }) => void
  actions: () => void
}>()
const attrs = useAttrs()
const checkedKeys = ref(
  props.columns.filter(v => !v.hidden).map(v => v.key),
)
const checkedColumns = computed<any[]>(() => {
  return props.columns.filter(v =>
    checkedKeys.value.includes(v.key),
  )
})

const route = useRoute()
function clickDownload() {
  if (props.customDownload) {
    emits('download', unref(checkedColumns))
    return
  }
  const { exportXlsx } = useSimpleExportLists<T>({
    columns: checkedColumns.value,
    lists: props.lists,
  })

  exportXlsx(route.meta.title)
}

watch(() => props.columns, () => {
  checkedKeys.value = props.columns.filter(v => !v.hidden).map(v => v.key)
}, { deep: true })
</script>

<template>
  <div class="width-fill lists-head flex">
    <div v-if="$slots.actions" class="flex-fillRemaining lists-actions">
      <slot name="actions" />
    </div>
    <div v-if="showToolbox" class="margin-left-auto flex-incompressible lists-toolbox self-end">
      <ElPopover :teleported="false" :width="popoverWidth">
        <template #reference>
          <ElButton type="primary" :icon="Filter" plain circle />
        </template>
        <div class="max-h-lg overflow-auto">
          <ElCheckboxGroup v-model="checkedKeys">
            <ElCheckbox
              v-for="column in columns" :key="column.key" :value="column.key"
              :disabled="column.type !== undefined" style="display: flex"
            >
              {{ column.label }}
            </ElCheckbox>
          </ElCheckboxGroup>
        </div>
      </ElPopover>
      <ElTooltip v-if="!hideDownload" content="导出" placement="top">
        <ElButton class="margin-left-xs" type="success" :icon="Download" plain circle @click="clickDownload" />
      </ElTooltip>
    </div>
  </div>
  <ElTable
    v-loading="loading" element-loading-custom-class="global-loading" class="table-lists-table overflow-auto"
    :class="{ 'no-border-bottom': noBorderBottom }" border :height="height" :data="lists" style="user-select: text"
    v-bind="attrs"
  >
    <template #empty>
      <TableEmpty />
    </template>
    <template
      v-for="{
        key,
        type,
        render,
        ...column
      } in checkedColumns" :key="key"
    >
      <ElTableColumn v-if="type" :type="type" v-bind="column" />
      <ElTableColumn v-else-if="render" v-bind="column">
        <template #default="scoped">
          <RenderComponent :render="render" :row="scoped.row" :column="scoped.column" :index="scoped.$index" />
          <!-- <component :is="render(row)" :row="row" :column="col"></component> -->
        </template>
      </ElTableColumn>
      <ElTableColumn v-else v-bind="column" />
    </template>
    <ElTableColumn
      v-if="$slots.operate" label="操作" prop="operate" :align="operateAlign" :width="operateWidth"
      :fixed="$slots.operate ? 'right' : undefined"
    >
      <template #default="scoped">
        <slot name="operate" :row="scoped.row" :column="scoped.column" :index="scoped.$index" />
      </template>
    </ElTableColumn>
  </ElTable>
</template>

<style scoped>
.lists-actions {
  &> :not(form) {
    margin-bottom: 18px;
  }
}

.lists-toolbox {
  margin-bottom: 18px;
}

.table.no-border-bottom :deep(.el-table__inner-wrapper::before) {
  display: none;
}
</style>
